package engine;

import java.util.ArrayList;

/**
 * A class to cache courses with calculated edgelists and way flags.
 * @author Johnny
 */
class Path {
    private Unit parent;
    private Edge[] edges;
    private int[] wayList;

    public Path(Unit parent, ArrayList<Edge> edgeList) {
        this.parent = parent;
        revalidate(edgeList);
    }

    /**
     * Recreates the path according to the unit's course list.
     */
    public void revalidate(ArrayList<Edge> edgeList) {
        int n = parent.getCourseNr();
        if (n < 2)  // A course with less than 2 nodes is not valid.
            return;
        Node[] course = parent.getCourse().toArray(new Node[n]);
        edges = new Edge[n-1];  // Minus 1 as the edges are situate between nodes
        wayList = new int[n-1];
        for (int i = 1; i < n; i++) {
            Edge middle = null;
            int way = 0;
            for (Edge edge : edgeList) {
                way = edge.suitable(course[i-1].getId(), course[i].getId());
                if (way != 0) {
                    middle = edge;
                    break;
                }
            }
            edges[i - 1] = middle;
            wayList[i - 1] = way;
        }
    }

    /**
     * Returns the place to look for a position.
     * @param inst the instance containing the schedule.
     * @param now the time when the position should be calculated.
     * @return a class containing the edge and the percentage where the
     * abstract position should be searched for or null if the unit in this
     * instance is not course.
     */
    public LookUpData getPos(Instance inst, Time now) {
        int n = inst.getScheduleNr();
        if (n < 2) // A course with less than 2 nodes is not valid.
            return null;
        Time[] schedules = inst.getSchedules().toArray(new Time[n]);

        // Check if the time is in the interval
        if (now.getTotalSeconds() - schedules[0].getTotalSeconds() < 0)  //
            return null;
        if (now.getTotalSeconds() - schedules[n-1].getTotalSeconds() > 0)
            return null;

        int upper = 0;
        for (int i = 1; i < n; i++) {
            if (now.substract(schedules[i]).getTotalSeconds() <= 0) {
                // If i've found the time the 'now' time, I stop
                upper = i;
                break;
            }
        }
        // Let's calculate the total length of the time between two schedule points
        int length = schedules[upper].substract(schedules[upper - 1]).getTotalSeconds();
        // Let's calculate the length of time between the 'now' time and the previous
        // schedule point.
        int delta = now.substract(schedules[upper - 1]).getTotalSeconds();
        // Let's calculate the percentage of the time "distance"
        float perc = ((float)delta * 100) / length;
        if (wayList[upper - 1] == -1)
            // If it's in the other way, we return the percentage complement
            perc = 100 - perc;

        return new LookUpData(edges[upper - 1], perc);
    }
}
